x86/AMD-Vi: Fix IVRS HPET special->handle override
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Mon, 30 Sep 2013 12:00:44 +0000 (14:00 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 30 Sep 2013 12:00:44 +0000 (14:00 +0200)
The current logic does not handle the case when HPET special->handle
is invalid in IVRS. On such system, the following message is shown:

(XEN) AMD-Vi: Failed to setup HPET MSI remapping: Wrong HPET

This patch will allow the ivrs_hpet[<handle>]=<sbdf> to override the
IVRS.  Also, it removes struct hpet_sbdf.iommu since it is not
used anywhere in the code.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
xen/drivers/passthrough/amd/iommu_acpi.c
xen/drivers/passthrough/amd/iommu_intr.c
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h

index c3b9631c1479a7092c45d8fbda1a1eb93a69e3b3..fca203707dc54f41894f3bd60cef0aab31538c97 100644 (file)
@@ -674,7 +674,7 @@ static void __init parse_ivrs_hpet(char *str)
     hpet_sbdf.id = id;
     hpet_sbdf.bdf = PCI_BDF(bus, dev, func);
     hpet_sbdf.seg = seg;
-    hpet_sbdf.cmdline = 1;
+    hpet_sbdf.init = HPET_CMDL;
 }
 custom_param("ivrs_hpet[", parse_ivrs_hpet);
 
@@ -789,20 +789,28 @@ static u16 __init parse_ivhd_device_special(
         }
         break;
     case ACPI_IVHD_HPET:
-        /* set device id of hpet */
-        if ( hpet_sbdf.iommu ||
-             (hpet_sbdf.cmdline && hpet_sbdf.id != special->handle) )
+        switch (hpet_sbdf.init)
         {
-            printk(XENLOG_WARNING "Only one IVHD HPET entry is supported\n");
+        case HPET_IVHD:
+            printk(XENLOG_WARNING "Only one IVHD HPET entry is supported.\n");
             break;
-        }
-        hpet_sbdf.id = special->handle;
-        if ( !hpet_sbdf.cmdline )
-        {
+        case HPET_CMDL:
+            AMD_IOMMU_DEBUG("IVHD: Command line override present for HPET %#x "
+                            "(IVRS: %#x devID %04x:%02x:%02x.%u)\n",
+                            hpet_sbdf.id, special->handle, seg, PCI_BUS(bdf),
+                            PCI_SLOT(bdf), PCI_FUNC(bdf));
+            break;
+        case HPET_NONE:
+            /* set device id of hpet */
+            hpet_sbdf.id = special->handle;
             hpet_sbdf.bdf = bdf;
             hpet_sbdf.seg = seg;
+            hpet_sbdf.init = HPET_IVHD;
+            break;
+        default:
+            ASSERT(0);
+            break;
         }
-        hpet_sbdf.iommu = iommu;
         break;
     default:
         printk(XENLOG_ERR "Unrecognized IVHD special variety %#x\n",
index 213f4d7bab6d782db0bfff13bbab17631be8e577..c1b76fb9d036a1d75c9bff300700a15d98818636 100644 (file)
@@ -598,10 +598,16 @@ int __init amd_setup_hpet_msi(struct msi_desc *msi_desc)
     unsigned long flags;
     int rc = 0;
 
-    if ( msi_desc->hpet_id != hpet_sbdf.id || !hpet_sbdf.iommu )
+    if ( hpet_sbdf.init == HPET_NONE )
     {
-        AMD_IOMMU_DEBUG("Failed to setup HPET MSI remapping: %s\n",
-                        hpet_sbdf.iommu ? "Wrong HPET" : "No IOMMU");
+        AMD_IOMMU_DEBUG("Failed to setup HPET MSI remapping."
+                        " Missing IVRS HPET info.\n");
+        return -ENODEV;
+    }
+    if ( msi_desc->hpet_id != hpet_sbdf.id )
+    {
+        AMD_IOMMU_DEBUG("Failed to setup HPET MSI remapping."
+                        " Wrong HPET.\n");
         return -ENODEV;
     }
 
index 3e6961d5c0dec252684cea03fa4dd44873c26d08..b5abc8ffe483c26f3a218c1dc7fa8acd8757a0e6 100644 (file)
@@ -108,8 +108,11 @@ extern struct ioapic_sbdf {
 
 extern struct hpet_sbdf {
     u16 bdf, seg, id;
-    bool_t cmdline;
-    struct amd_iommu *iommu;
+    enum {
+        HPET_NONE,
+        HPET_CMDL,
+        HPET_IVHD,
+    } init;
 } hpet_sbdf;
 
 extern void *shared_intremap_table;